#include <stdio.h>
#include <malloc.h>
#include "symtable.h"
#include <assert.h>

//测试结果信息
struct TestInfo
{
    int success_count;
    int err_count;
};
//测试创建链表不为空
int Test_LinkTable_new_1()
{
    struct Link* oLink = LinkTable_new();
    int result = My_Assert(oLink != NULL,"link table is NULL");
    return result;
}
//测试链表全部释放 释放后，无法确定，用valgrind进行检测内存泄露
int Test_LinkTable_free_1()
{
    int result = 0;
    struct Link* oLink = LinkTable_new();
    Link_put(oLink, "a", "1a");
    Link_put(oLink, "b", "2b");
    Link_put(oLink, "c", "3c");
    Link_put(oLink, "d", "4d");
    LinkTable_free(oLink);//释放后，oLink仍然指向原地址
    // 内存释放后无法判断
    return result;
}
//测试链表长度为2
int Test_LinkTable_getLength_1()
{
    struct Link* oLink = LinkTable_new();
    Link_put(oLink, "a", "1a");
    Link_put(oLink, "b", "2b");
    int count = LinkTable_getLength(oLink);
    LinkTable_free(oLink);
    int result = My_Assert(count == 2, "length is err");
    return result;
}
//测试向链表中添加两个元素
int Test_Link_put_1()
{
    struct Link* oLink = LinkTable_new();
    Link_put(oLink, "a", "1a");
    Link_put(oLink, "b", "2b");
    int cmp1 = strcmp((char*)oLink->Value, (char*)"1a");
    int cmp2 = strcmp((char*)oLink->Next->Value, (char*)"2b");
    int result = My_Assert((cmp1 == 0 && cmp2 == 0),"put is err"); 
    LinkTable_free(oLink);
    return result;
}
//测试替换链表中第三个value值
int Test_Link_replace_1()
{
    int result = 0;
    struct Link* oLink = LinkTable_new();
    Link_put(oLink, "a", "1a");
    Link_put(oLink, "b", "2b");
    Link_put(oLink, "c", "3c");
    Link_put(oLink, "d", "4d");
    char* replace_str = "replace";
    Link_replace(oLink,"c",replace_str);
    int cmp = strcmp((char*)oLink->Next->Next->Value,replace_str);
    result = My_Assert(cmp == 0, "replace is err");
    LinkTable_free(oLink);
    return result;
}
//测试链表中是否包含key的元素
int Test_Link_constains_1()
{
    int result = 0;
    struct Link* oLink = LinkTable_new();
    Link_put(oLink, "a", "1a");
    Link_put(oLink, "b", "2b");
    Link_put(oLink, "c", "3c");
    Link_put(oLink, "d", "4d");
    int back_int = Link_constains(oLink,"b");
    result = My_Assert(back_int == 1, "constains is err");
    LinkTable_free(oLink);
    return result;
}
//测试根据某key获取对应的value值
int Test_Link_get_1()
{
    int result = 0;
    struct Link* oLink = LinkTable_new();
    Link_put(oLink, "a", "1a");
    Link_put(oLink, "b", "2b");
    Link_put(oLink, "c", "3c");
    Link_put(oLink, "d", "4d");
    void* back_void = Link_get(oLink,"c");
    int back_int = strcmp((char*)back_void,"3c");
    result = My_Assert(back_int == 0, "get is err");
    LinkTable_free(oLink);
    return result;
}
//测试链表中4个元素，删除一个，剩余3个
int Test_Link_remove_1()
{
    int result = 0;
    struct Link* oLink = LinkTable_new();
    Link_put(oLink, "a", "1a");
    Link_put(oLink, "b", "2b");
    Link_put(oLink, "c", "3c");
    Link_put(oLink, "d", "4d");
    void* old_node = Link_remove(oLink, "b");
    char* old_node_value = (char*)((struct Link*)old_node)->Value;
    int old_node_cmp = strcmp(old_node_value,"2b");
    free((struct Link*)old_node);
    int node1_cmp = strcmp((char*)oLink->Value, "1a");
    int node2_cmp = strcmp((char*)oLink->Next->Value, "3c");
    int node3_cmp = strcmp((char*)oLink->Next->Next->Value, "4d");
    result = My_Assert(old_node_cmp == 0
		      && node1_cmp == 0
		      && node2_cmp == 0
		      && node3_cmp == 0,
		      "remove is err");
    LinkTable_free(oLink);
    return result;
}
//断言，expression为0，则表示通过；不为0则表示不通过，同时输出msg信息
int My_Assert(int expression, const char* msg)
{
    int result = 1;
    assert(expression);
    /*
    if(expression)
    {
	result = 1;
    }
    else
    {
	printf("Error: %s\n",msg);
	result = 0;
    }
    */
    return result;
}
//计算测试结果信息
void CalcCount(int back_int, struct TestInfo* info)
{
    if(back_int)
    {
	info->success_count++;
    }
    else
    {
	info->err_count++;
    }
}

int main()
{
    printf("------------Begin Unit test-------------\n");

    struct TestInfo info;
    info.success_count = 0;
    info.err_count = 0;
    int back_int = -1;

    back_int = Test_LinkTable_new_1();
    CalcCount(back_int, &info);
    
//  back_int = Test_LinkTable_free_1();//此测试用例没有用，释放后无法判断
//  CalcCount(back_int, &info); //用valgrind进行测试

    back_int = Test_LinkTable_getLength_1();
    CalcCount(back_int, &info);

    back_int = Test_Link_put_1();
    CalcCount(back_int, &info);

    back_int = Test_Link_replace_1();
    CalcCount(back_int, &info);

    back_int = Test_Link_constains_1();
    CalcCount(back_int, &info);

    back_int = Test_Link_get_1();
    CalcCount(back_int, &info);

    back_int = Test_Link_remove_1();
    CalcCount(back_int, &info);

    printf("Passed : %d\n",info.success_count);
    printf("Failed : %d\n",info.err_count);

    printf("-------------End Unit test--------------\n");

    return 0;
}
